iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 24
1
Modern Web

從0.5開始的JavaScript系列 第 24

Day24 Promise 詳解(2/2)

  • 分享至 

  • xImage
  •  

昨日講完了 Promise 的特性與基本用法,今日再來討論更深入的應用。

Promise

首先就是剩下的兩個方法: Promise.allPromise.race

Promise.all

Promise.all 能夠將傳入的多個 Promise 同時執行(平行處理),並且等到所有傳入的 Promise 都回應狀態後,才會進入 then,而 then 中的 resolve function 傳入的參數即為一開始傳入的所有 Pormiseresolve 回傳值。

這邊一樣呼叫昨天網美小花的例子,

var willTogether = function(money) {
    return new Promise(function (resolve, reject) {
      if(money > 100) {
          resolve("我愛你 " + money + " 元先生");
      } else {
          reject(new Error('你是一個好人,但你值得更好的人'));
      }
    });
}

我們昨天的範例是一次只有一位追求者,所以 300 元先生必須等到網美小花回應 200 元先生後,才能進行追求,

willTogether(200)
.then(function(val) {
    // 當網美小花回應 Mr.200 後
    // Mr.300 接著追求
    return willTogether(300);
})
.then(function(val) {
    // 網美小花回應 Mr.300
})
.catch(function(err) {
    console.log(err);
});

But

現實生活中有這種事情,追求者會輪流排隊嗎?

好人卡多到可以打牌的小王覺得不行!

為了更貼近真實案例,所有追求者應該是同時追求,但是還是為了公平,所以會等到網美小花回應所有追求者後,再由他統一公布所有追求者的結果。

而好人小王就是 Promise.all,程式碼可以寫成這樣,

Promise.all([willTogether(200), willTogether(300)])
.then(function(val) {
    console.log(val);
    // ["我愛你 200 元先生", "我愛你 300 元先生"]
})

因為傳入多個 Promise,所有結果會存到一個陣列中。

好人小王覺得自己提供追求者更多機會,網美小花也同時有了多個男友,可喜可賀、可喜可賀。

重點整理

Promise.all :

  1. 用 Array 包起來,能夠傳入多個 Promise 同時執行。
  2. 等到所有 Promise 回傳狀態後,才會接著進行下一步。
  3. thenresolve function 將會收到所有 Promise 回傳的結果。

但是使用上要非常注意,因為只要傳入的 Promise 中有一個 reject,將會導致直接進入 catch,也不會收到其他 resolve 狀態的回傳值。

像是這樣,就算 willTogether(200) 的狀態應該會是 resolve,但是 willTogether(50)reject 導致直接進入 catchthen 中也不會印出 Mr.200

Promise.all([willTogether(200), willTogether(50)])
.then(function(val) {
    console.log(val); // 不會顯示出 Mr.200
})
.catch(function(err) {
    console.log(err); // sorry
})

簡單來講,就是只要有一個失敗,其他人也涼啦!

Promise.race

上方都理解後,Promise.race 也差不多理解了,它和 Promise.all 的差別在於,Promise.race 只要有一個完成,就會進入 then,不會等剩下的 Promise

我們把程式碼改一下,讓網美小花的變成來者不拒,但是考慮時間變成隨機(0~3秒),
順便也把函數改成箭頭函式的寫法:

var willTogether = (name) => {
    return new Promise((resolve, reject) => {
        var s = Math.floor(Math.random() * 4);
        setTimeout(() => resolve("恭喜你: " + name), s * 1000);
    });
}

忘記箭頭函式的可以到 Day6 複習。

接下來就是有多個競爭者同時追求,看誰最幸運,第一個被網美小花回應!

Promise.race([willTogether("Bob"), willTogether("Tom"), willTogether("Ken")])
.then(function(val) {
    console.log(val); // 顯示第一個完成的
})
.catch(function(err) {
    console.log(err);
})

執行結果(每次都不一樣)

至此 Promise 的四個方法都已講完

  • Promise.resolve
  • Promise.reject
  • Promise.all
  • Promise.race

下一篇會介紹被譽為處理非同步的最佳方案: awaitasync

今日的分享就到這,我們明天見/images/emoticon/emoticon51.gif


上一篇
Day23 Promise 詳解(1/2)
下一篇
Day25 優雅的 Await、Async
系列文
從0.5開始的JavaScript30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言